package com.ezops.poc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.ezops.poc.bo.IClientModel;
import com.ezops.poc.bo.TradeStatus;
import com.ezops.poc.validations.TradeIndentifier;

/**
 * data access layer for accesssing the client data. (Can be trating as staging
 * layer.)
 * 
 * @author vgaurav
 * 
 */
@Repository(value = "clientDAO")
public class ClientModelDAO {


	@Autowired
	private UtilityDAO utilDao;

	@Autowired
	private EzopsClientModelPesistanceManager manager;

	private static final Logger logger = LoggerFactory
			.getLogger(ClientModelDAO.class);

	private static final String UDPATE_STATUS = "UPDATE EZOPSDB.CLIENT_TRADES SET STATUS=? WHERE EZOPS_ID=?";
	private static final String UDPATE_OT_ID = "UPDATE EZOPSDB.CLIENT_TRADES SET STATUS=?, OT_ID=? WHERE EZOPS_ID=?";
	private static final String GET_TRADE_INDENTIFIER = "SELECT  EZOPS_ID, CLIENT_ID, ASSET_ID, ACTION,FILE_NAME ,CLIENT_TRADE_ID FROM EZOPSDB.CLIENT_TRADES WHERE EZOPS_ID=?";

	@Autowired
	private JdbcTemplate jdbcTemplate;

	public ClientModelDAO() {
	}

	/**
	 * Update the status of row identified by ezopsId
	 * 
	 * @param ezopsModel
	 * @param status
	 */
	public void update(int ezopsId, TradeStatus status) {
		logger.debug("Updating the stats of ezopsId-" + ezopsId + " to "
				+ status.getStatus());
		jdbcTemplate.update(UDPATE_STATUS, status.getStatus(), ezopsId);

	}
	
	/**
	 * Update the status and OT_ID for the ezopsId.
	 * @param ezopsId
	 * @param status
	 * @param otId
	 */
	public void update(int ezopsId, TradeStatus status, int otId) {
		logger.debug("Updating the stats of ezopsId-" + ezopsId + " to "
				+ status.getStatus());
		jdbcTemplate.update(UDPATE_OT_ID, status.getStatus(),otId, ezopsId);
	}

	/**
	 * Fetch the trade identifier ( properties which will uniquely identify the
	 * trades ) for the @param ezopsId
	 * 
	 * @param ezopsId
	 * @return
	 */
	public TradeIndentifier getTradeIdentifier(final int ezopsId) {
		logger.debug("Fetching trade idetifier of ezopsId-" + ezopsId);
		List<TradeIndentifier> identifier = jdbcTemplate.query(
				new PreparedStatementCreator() {

					@Override
					public PreparedStatement createPreparedStatement(
							Connection con) throws SQLException {
						PreparedStatement ps =con.prepareStatement(GET_TRADE_INDENTIFIER);
						ps.setInt(1, ezopsId);
						return ps;
					}
				}, new RowMapper<TradeIndentifier>() {

					@Override
					public TradeIndentifier mapRow(ResultSet rs, int rowNum)
							throws SQLException {
						TradeIndentifier tradeIdentifier = new TradeIndentifier();
						tradeIdentifier.setEzopsId(rs.getInt("EZOPS_ID"));
						tradeIdentifier.setClientId(rs.getInt("CLIENT_ID"));
						tradeIdentifier.setAssetId(rs.getInt("ASSET_ID"));
						tradeIdentifier.setAction(rs.getString("ACTION"));
						tradeIdentifier.setFileName(rs.getString("FILE_NAME"));
						tradeIdentifier.setClientTradeId(rs
								.getInt("CLIENT_TRADE_ID"));
						return tradeIdentifier;
					}

				});
		return identifier.get(0);
	}

	/**
	 * Persist the ClientModel.
	 * 
	 * @param transientModels
	 */
	public void persist(List<IClientModel> transientModels) {
		if (transientModels == null || transientModels.isEmpty()) {
			return;
		}
		int batchId = utilDao.getNextBatchId();

		for (IClientModel transientModel : transientModels) {
			transientModel.setBatchId(batchId);
			persist(transientModel, batchId);
		}
	}

	/**
	 * Persist the list of client models.
	 * 
	 * @param transientModel
	 * @param batchId
	 */
	public void persist(IClientModel transientModel, int batchId) {
		try {
			logger.info("Adding trade record to database. trade id: "
					+ transientModel.getClientTradeId() + " action: "
					+ transientModel.getField("action"));

			final EzopsPersistanceStrategy strategy = manager.getStrategy(
					transientModel.getClientId(), transientModel.getAssetId());

			final Object[] args = strategy.getColumnValues(transientModel);

			/*
			 * KeyHolder holder = new GeneratedKeyHolder();
			 * 
			 * PreparedStatementCreator creator = new PreparedStatementCreator()
			 * {
			 * 
			 * @Override public PreparedStatement createPreparedStatement(
			 * Connection connection) throws SQLException { PreparedStatement ps
			 * = connection.prepareStatement(strategy .getQuery().toString(),
			 * Statement.RETURN_GENERATED_KEYS); if (args != null) { for (int i
			 * = 0; i < args.length; i++) { Object arg = args[i]; doSetValue(ps,
			 * i + 1, arg);
			 * 
			 * } } return ps; }
			 * 
			 * private void doSetValue(PreparedStatement ps, int
			 * parameterPosition, Object argValue) throws SQLException {
			 * StatementCreatorUtils.setParameterValue(ps, parameterPosition,
			 * SqlTypeValue.TYPE_UNKNOWN, argValue);
			 * 
			 * } };
			 */

			// HACK - SET THE EZOPS ID
			args[0] = utilDao.getNextEzopsId();
			jdbcTemplate.update(strategy.getQuery(), args);

			transientModel.setEzopsId((Integer) args[0]);

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

}
